#pragma once

#include <cstdint>
#include <memory>
#include <vector>
#include <map>
#include <set>
#include <mutex>

#include "r_socket.h"

namespace eniac
{

class r_socket_obj_manager
{
public:
    r_socket_obj_manager() = default;
    r_socket_obj_manager(const r_socket_obj_manager& other) = delete;
    r_socket_obj_manager(r_socket_obj_manager&& other) = delete;
    r_socket_obj_manager& operator=(const r_socket_obj_manager& other) = delete;
    r_socket_obj_manager& operator=(r_socket_obj_manager&& other) = delete;
    ~r_socket_obj_manager() = default;

    static r_socket_obj_manager* get_instance();

    r_socket::ptr create_socket_obj(r_socket_type type);
    r_socket::ptr get_socket_obj_by_id(std::int32_t id);
    r_socket::ptr get_socket_obj_by_fd(std::int32_t fd);
    void update_socket_obj(r_socket::ptr obj);
    void remove_socket_obj(std::int32_t id);
    std::set<r_socket::fd_t> get_all_socket_fds();
    std::int32_t get_fd_num();
    r_socket::ptr is_partner_exists(r_socket::ptr self, r_socket::ptr in_partner);

private:
    static std::int32_t m_last_socket_id;
    r_socket::id_ptr_map m_id_socket_map {};
    r_socket::fd_ptr_map m_fd_socket_map {};
    std::map<r_socket::id_t, r_socket::fd_t> m_old_fds {};
    std::recursive_mutex m_socket_obj_mutex{};
};

}